"use client";

import { Environment, OrbitControls, useGLTF } from "@react-three/drei";
import { Canvas, useThree } from "@react-three/fiber";
import type { OrbitControls as OrbitControlsImpl } from "three/examples/jsm/controls/OrbitControls.js";
import { useSearchParams } from "next/navigation";
import { Suspense, useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Slider } from "@/components/ui/slider";

interface ModelViewerProps {
    modelPath: string;
    controls?: {
        enableDamping?: boolean;
        dampingFactor?: number;
        enableZoom?: boolean;
        enablePan?: boolean;
        enableRotate?: boolean;
        minDistance?: number;
        maxDistance?: number;
        minPolarAngle?: number;
        maxPolarAngle?: number;
        autoRotate?: boolean;
    };
    environment?: {
        background?: boolean;
        blur?: number;
        brightness?: number;
        hdr?: string;
    };
}

// 自定义hook来获取文件URL
function useModelUrl(modelPath: string) {
    return `/api/files/serve?path=${encodeURIComponent(modelPath)}`;
}

function Model({ modelPath, controls }: { modelPath: string; controls?: ModelViewerProps["controls"] }) {
    const modelUrl = useModelUrl(modelPath);
    const { scene } = useGLTF(modelUrl);
    const { camera, gl } = useThree();
    const controlsRef = useRef<OrbitControlsImpl | null>(null);

    useEffect(() => {
        // 计算包围盒
        const box = new THREE.Box3().setFromObject(scene);
        const center = box.getCenter(new THREE.Vector3());
        const size = box.getSize(new THREE.Vector3());
        const maxDim = Math.max(size.x, size.y, size.z);

        // 将模型居中
        scene.position.sub(center);

        // 计算合适的相机距离
        const fov = (camera as THREE.PerspectiveCamera).fov * (Math.PI / 180); // 转换为弧度
        const distance = Math.abs(maxDim / (2 * Math.tan(fov / 2))) * 1.5; // 1.5倍安全距离

        // 设置相机位置
        camera.position.set(distance, distance, distance);
        camera.lookAt(0, 0, 0);
        camera.updateMatrixWorld();

        // 动态调整相机的 near 和 far 参数
        const near = maxDim * 0.01; // near 为模型最大尺寸的 1%
        const far = distance * 10; // far 为相机距离的 10 倍
        (camera as THREE.PerspectiveCamera).near = near;
        (camera as THREE.PerspectiveCamera).far = far;
        (camera as THREE.PerspectiveCamera).updateProjectionMatrix();

        // 更新渲染器视口
        gl.setSize(gl.domElement.clientWidth, gl.domElement.clientHeight);

        // 动态调整轨道控制器的距离限制
        if (controlsRef.current) {
            controlsRef.current.minDistance = maxDim * 0.1; // 最小距离为模型尺寸的10%
            controlsRef.current.maxDistance = distance * 3; // 最大距离为初始距离的3倍
        }
    }, [scene, camera, gl]);

    return (
        <>
            <primitive object={scene} />
            <OrbitControls
                ref={controlsRef as any}
                enableDamping={controls?.enableDamping ?? true}
                dampingFactor={controls?.dampingFactor ?? 0.1}
                enableZoom={controls?.enableZoom ?? true}
                enablePan={controls?.enablePan ?? true}
                enableRotate={controls?.enableRotate ?? true}
                minDistance={controls?.minDistance ?? 0.1}
                maxDistance={controls?.maxDistance ?? 1000}
                minPolarAngle={controls?.minPolarAngle ?? 0}
                maxPolarAngle={controls?.maxPolarAngle ?? Math.PI}
                // 添加平滑的缩放和旋转

                // 自动旋转（可选）
                autoRotate={controls?.autoRotate ?? false}
                autoRotateSpeed={1}
            />
        </>
    );
}

function ModelViewer({ modelPath, controls, environment }: ModelViewerProps) {
    const [hdrExposure, setHdrExposure] = useState(1);
    const [ambientLight, setAmbientLight] = useState(0.1);

    // 获取HDR文件路径
    const getHdrFile = () => {
        const hdr = environment?.hdr || "indoor.hdr";
        // 在生产环境中也使用API路由
        return `/hdr/${hdr}`;
    };

    // 场景新增一个环境光，默认强度0.1，右上角新增一个参数调整面板，支持调节hdr 曝光度和 环境光亮度，和环境光亮度
    return (
        <div className="w-full h-screen bg-black">
            <Card className="fixed top-4 right-4 z-10 w-96">
                <CardHeader className="hidden">
                    <CardTitle> 环境光亮度 </CardTitle>
                    <CardDescription> 环境光亮度 </CardDescription>
                </CardHeader>
                <CardContent>
                    <div className="flex flex-col gap-2">
                        <div className="grid grid-cols-32 gap-2">
                            <strong className="col-span-8 text-sm">HDR曝光</strong>
                            <Slider className="col-span-20" value={[hdrExposure]} min={0} step={0.01} max={2} onValueChange={(value) => setHdrExposure(value[0])} />
                            <span className="col-span-4 text-right">{hdrExposure}</span>
                        </div>
                        <div className="grid grid-cols-32 gap-2">
                            <strong className="col-span-8 text-sm">环境光亮度</strong>
                            <Slider className="col-span-20" value={[ambientLight]} min={0} step={0.01} max={1} onValueChange={(value) => setAmbientLight(value[0])} />
                            <span className="col-span-4 text-right">{ambientLight}</span>
                        </div>
                    </div>
                </CardContent>
            </Card>
            <Canvas camera={{ position: [0, 0, 5], fov: 50, near: 0.1, far: 1000 }} style={{ background: "transparent" }} gl={{ antialias: true, alpha: true }}>
                <Suspense fallback={null}>
                    {environment?.background !== false && <Environment background environmentIntensity={hdrExposure} blur={environment?.blur ?? 100} files={[getHdrFile()]} />}
                    <ambientLight intensity={ambientLight} />

                    <Model modelPath={modelPath} controls={controls} />
                </Suspense>
            </Canvas>
        </div>
    );
}

function App() {
    const searchParams = useSearchParams();
    const modelPath = searchParams.get("model");

    if (!modelPath) {
        return (
            <div className="flex items-center justify-center h-screen bg-black text-white">
                <div className="text-center">
                    <h1 className="text-2xl font-bold mb-4">模型路径未指定</h1>
                    <p className="text-gray-400">请通过 URL 参数指定要查看的模型路径</p>
                    <p className="text-sm text-gray-500 mt-2">示例: /view?model=path/to/model.glb</p>
                </div>
            </div>
        );
    }

    // 解析URL参数
    const controls = {
        enableDamping: searchParams.get("damping") !== "false",
        dampingFactor: parseFloat(searchParams.get("dampingFactor") || "0.05"),
        enableZoom: searchParams.get("zoom") !== "false",
        enablePan: searchParams.get("pan") === "true",
        enableRotate: searchParams.get("rotate") !== "false",
        minDistance: parseFloat(searchParams.get("minDistance") || "0.1"),
        maxDistance: parseFloat(searchParams.get("maxDistance") || "1000"),
        minPolarAngle: parseFloat(searchParams.get("minPolarAngle") || "0"),
        maxPolarAngle: parseFloat(searchParams.get("maxPolarAngle") || String(Math.PI)),
        autoRotate: searchParams.get("autoRotate") === "true",
    };

    const environment = {
        background: searchParams.get("background") !== "false",
        blur: parseFloat(searchParams.get("blur") || "1"),
        brightness: parseFloat(searchParams.get("brightness") || "1"),
        hdr: searchParams.get("hdr") || "indoor.hdr", // 支持HDR参数
    };

    return <ModelViewer modelPath={modelPath} controls={controls} environment={environment} />;
}

export default function Page() {
    return (
        <Suspense>
            <App />
        </Suspense>
    );
}
